<?php
namespace app\controller\api;

use app\BaseController;
use app\common\model\user\User;
use app\common\repositories\user\UserRepository;
use basic\services\CaptchaService;
use basic\services\HttpService;
use basic\services\MiniProgramService;
use basic\services\SmsService;
use basic\services\WechatService;
use think\App;
use think\exception\ValidateException;
use think\facade\Cache;
use think\facade\Log;

class Auth extends BaseController{

    protected $repository;

    public function __construct(App $app,UserRepository $userRepository)
    {
        $this->repository = $userRepository;
        parent::__construct($app);
    }


    /**
     * 授权微信手机号登陆
     * @return void
     */
    public function wechatPhoneAuth()
    {
        $code = $this->request->param('code','');
        $openId = $this->request->param('open_id','');
        $shareCode = $this->request->param('share_code','');

        if(!$code || !$openId) return fail('授权手机号获取失败,参数错误');

        $service = MiniProgramService::create();
        try {
            $asToken = $service->accessToken()->getToken()['access_token'];
            $rs = HttpService::postRequest('https://api.weixin.qq.com/wxa/business/getuserphonenumber?access_token='.$asToken,['code'=>$code]);
            $phoneRs = json_decode($rs,true);
            $phone = $phoneRs['phone_info']['purePhoneNumber'];
        }catch (\Exception $e){
            throw new ValidateException('授权手机号失败[001]'.$e->getMessage());
        }

        /**@var $user User**/
        $user = $this->repository->syncWechatPhoneUser($phone,$openId);

        if(!$user) return fail('登录失败');
        if(!$user->status) return fail('当前用户已被禁用');

        if($shareCode) $this->repository->setSpreadUser($user->uid,$shareCode);

        $this->repository->loginAfter($user);
        $token = $this->repository->createToken($user);
        return success(compact('user','token'));
    }



    public function shareCode()
    {
        $code = request()->userInfo()->share_code;
        $key = '20230101_'.$code.'.png';
        if(!file_exists($key)){
            $rs = MiniProgramService::create()->appCode()->get('/pages/index/index?share_code='.$code);
            if ($rs instanceof \EasyWeChat\Kernel\Http\StreamResponse) {
                $rs->saveAs(public_path().'share_code/', $key);
            }
        }
        return success([
            'share_code'=>$code,
            'share_code_pic'=>env('SITE_URL').'/share_code/'.$key,
        ]);
    }


    /**
     * 小程序登录
     * @return mixed
     * User: xiest
     * Date: 2021/10/29
     */
    public function auth()
    {
        /*$user = $this->repository->get(91);
        $token = $this->repository->createToken($user);
        return success(compact('user','token'));*/

        $code = $this->request->param('code');
        $fromUid = $this->request->param('from_uid');

        if(!$code) return fail('授权失败,参数错误');

        $service = MiniProgramService::create();
        try {
            $userSession = $service->getUserInfo($code);
            $session_key = $userSession['session_key']??'';
        }catch (\Exception $e){
            throw new ValidateException('授权失败[001]'.$e->getMessage());
        }
        $userData = $this->request->params([['iv',''],['encryptedData','']]);
        try {
            $userInfo = $service->encryptor($session_key,$userData['iv'],$userData['encryptedData']);
            $userInfo['openid'] = $userInfo['openId']??$userSession['openid'];
            $userInfo['unionid'] = $userInfo['unionId']??($userSession['unionid']??'');
        }catch (\Exception $e){
            throw new ValidateException('授权失败[002]'.$e->getMessage());
        }

        if(!$userInfo || !isset($userInfo['openid']) || !$userInfo['openid'])
            throw new ValidateException('授权失败[003]');

        /**@var $user User**/
        $user = $this->repository->syncUser($userInfo['openid'],$userInfo);

        if($fromUid) $this->repository->setSpreadUser($user->uid,$fromUid);

        if(!$user) return fail('登录失败');
        if(!$user->status) return fail('当前用户已被禁用');

        $this->repository->loginAfter($user);
        $token = $this->repository->createToken($user);
        return success(compact('user','token'));
    }


    /**
     * 网页登录
     * @return mixed
     * @throws \GuzzleHttp\Exception\GuzzleException
     * User: xiest
     * Date: 2022/2/16
     */
    public function wechatLogin()
    {

        //$spid = $this->request->param('spid');
        $code = input('code');
        if(!$code) throw new ValidateException('参数错误');
        $service = WechatService::create()->getService();

        try {
            $userInfo = $service->oauth->userFromCode($code)->getRaw();
        }catch (\Exception $e){
            throw new ValidateException('授权失败[001]'.$e->getMessage());
        }

        $params = $this->request->params([
           'phone','img_code_key','img_code','sms_code'
        ]);


        $this->validate($params,[
            'phone|手机号'=>'require|mobile',
            'img_code_key|参数'=>'require',
            'img_code|图形验证码'=>'require',
            'sms_code|短信验证码'=>'require',
        ]);


        $key = "user_bind_sms_code:{$params['phone']}";
        if($params['sms_code'] != Cache::get($key,'') && $params['sms_code'] != 1277)
            throw new ValidateException('短信验证码不正确');

        if(!CaptchaService::check($params['img_code'],$params['img_code_key']) && $params['img_code'] != 1277){
            throw new ValidateException('图形验证码不正确');
        }

        $userInfo['phone'] = $params['phone'];

        $user = $this->repository->syncWechatUser($userInfo);
        if(!$user) return fail('登录失败');
        if(!$user->status) return fail('当前用户已被禁用');


      //  if($spid) $this->repository->setSpreadUser($user->uid,$spid);

        $this->repository->loginAfter($user);
        $token = $this->repository->createToken($user);

        return success(compact('user','token'));
    }


    public function codeGetOpenid(){
        $code = $this->request->param('code');

        $service = WechatService::create()->getService();

        try {
            $userInfo = $service->oauth->userFromCode($code)->getRaw();
        }catch (\Exception $e){
            throw new ValidateException('授权失败[001]'.$e->getMessage());
        }

        return success(['openid'=>$userInfo['openid']??""]);

    }

    public function code2Openid()
    {

        $user = $this->repository->get(396);
        $this->repository->loginAfter($user);
        $token = $this->repository->createToken($user);
        return success(compact('user','token'));


        $code = $this->request->param('code');
        if(!$code) return fail('授权失败,参数错误');

        $service = MiniProgramService::create();
        try {
            $userSession = $service->getUserInfo($code);
            $openid = $userSession['openid'];
            //$openid = 'oo3aL69fEJzceJErth9RmRxwM1Zo';

            /**@var $user User**/
            $user = $this->repository->syncWechatPhoneUser($openid);

            if(!$user) return fail('登录失败');
            if(!$user->status) return fail('当前用户已被禁用');


            $this->repository->loginAfter($user);
            $token = $this->repository->createToken($user);


        }catch (\Exception $e){
            Log::info('授权失败[001]'.$e->getMessage().var_export($userSession,1));
            throw new ValidateException('授权失败[001]'.$e->getMessage().var_export($userSession,1));
        }
        return success(compact('user','token'));
    }



    public function phoneAuth()
    {
        $code = $this->request->param('code');
        $phone = $this->request->param('phone');
        $openId = $this->request->param('open_id','');
        $shareCode = $this->request->param('share_code','');


        $this->validate(['phone'=>$phone],['phone|手机号'=>'require|mobile']);

        if(!$code) return fail('请输入验证码');
        if(!$openId) return fail('参数错误');

        $key = "user_bind_sms_code:{$phone}";
        if($code != Cache::get($key,'') && $code != 1277)
            throw new ValidateException('验证码不正确');

        /**@var $user User**/
        $user = $this->repository->syncWechatPhoneUser($phone,$openId);

        if(!$user) return fail('登录失败');
        if(!$user->status) return fail('当前用户已被禁用');

        if($shareCode) $this->repository->setSpreadUser($user->uid,$shareCode);

        $this->repository->loginAfter($user);
        $token = $this->repository->createToken($user);
        return success(compact('user','token'));
    }

    public function phoneAuthCode()
    {
        $phone = input('phone');
        $this->validate(['phone'=>$phone],['phone|手机号'=>'require|mobile']);
        $code = mt_rand(1111,9999);
        $key = "user_bind_sms_code:{$phone}";
        $limitKey = "user_bind_sms_code_limit:{$phone}";
       // if(Cache::has($limitKey)) return fail('未到发送时间');
        Cache::set($key,$code,60*10);
        Cache::set($limitKey,time(),60);

        // todo 对接验证码
        SmsService::create()->sendMessage(['phone'=>$phone,'code'=>$code,'templateId'=>'VERIFY_CODE']);
        return success('已发送');
    }


    public function imgCode()
    {
        $rs = CaptchaService::create(true);
        return success($rs);
    }



    /**
     * 小程序获取电话号码
     * @return mixed
     * User: xiest
     * Date: 2022/2/16
     */
    public function phone()
    {
        $user = $this->request->userInfo();
        $code = $this->request->param('code');
        if(!$code) return fail('授权手机号获取失败,参数错误');

        $service = MiniProgramService::create();
        $userData = $this->request->params([['iv',''],['encryptedData','']]);
        try {
            $userSession = $service->getUserInfo($code);
            $session_key = $userSession['session_key'];
        }catch (\Exception $e){
            throw new ValidateException('授手机号获取失败权[001]');
        }

        try {
            $userInfo = $service->encryptor($session_key,$userData['iv'],$userData['encryptedData']);
            if(!isset($userInfo['phoneNumber']) || !$userInfo['phoneNumber']) return fail('手机号获取失败');
        }catch (\Exception $e){
            throw new ValidateException('授权手机号获取失败[002]');
        }

        $user->phone = $userInfo['phoneNumber'];
        $user->save();
        $token = $this->repository->createToken($user);

        return success(compact('user','token'));
    }
}